using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using DevExpress.Mvvm;
using DevExpress.Mvvm.DataAnnotations;
using DevExpress.Mvvm.Native;
using DevExpress.Mvvm.POCO;
using DevExpress.Utils.About;
using DevExpress.Xpf;
using DevExpress.Xpf.Bars;
using DevExpress.Xpf.Core;
using DevExpress.Xpf.DemoBase.Helpers;
using DevExpress.Xpf.Docking;
using DevExpress.Xpf.PropertyGrid;

namespace OneStress.ViewModels
{
    public class MainViewModel {
        CommandViewModel errorList;
        PanelWorkspaceViewModel lastOpenedItem;
        CommandViewModel loadLayout;
        CommandViewModel newFile;
        CommandViewModel newProject;
        CommandViewModel openFile;
        CommandViewModel openProject;
        CommandViewModel output;
        CommandViewModel properties;
        CommandViewModel save;
        CommandViewModel saveAll;
        CommandViewModel saveLayout;
        CommandViewModel searchResults;
        CommandViewModel solutionExplorer;
        DataManagerViewModel dataManagerViewModel;
        ObservableCollection<WorkspaceViewModel> workspaces;

        public MainViewModel() {
            ErrorListViewModel = CreatePanelWorkspaceViewModel<ErrorListViewModel>();
            OutputViewModel = CreatePanelWorkspaceViewModel<OutputViewModel>();
            PropertiesViewModel = CreatePanelWorkspaceViewModel<PropertiesViewModel>();
            SearchResultsViewModel = CreatePanelWorkspaceViewModel<SearchResultsViewModel>();
       
            Bars = new ReadOnlyCollection<BarModel>(CreateBars());
            InitDefaultLayout();
        }
        
        public ReadOnlyCollection<BarModel> Bars { get; private set; }
        public ErrorListViewModel ErrorListViewModel { get; private set; }
        public OutputViewModel OutputViewModel { get; private set; }
        public PropertiesViewModel PropertiesViewModel { get; private set; }
        public SearchResultsViewModel SearchResultsViewModel { get; set; }
        public DataManagerViewModel SolutionExplorerViewModel {
            get {
                if(dataManagerViewModel == null) {
                    dataManagerViewModel = CreatePanelWorkspaceViewModel<DataManagerViewModel>();
                }
                return dataManagerViewModel;
            }
        }
 
        public ObservableCollection<WorkspaceViewModel> Workspaces {
            get {
                if(workspaces == null) {
                    workspaces = new ObservableCollection<WorkspaceViewModel>();
                    workspaces.CollectionChanged += OnWorkspacesChanged;
                }


                return workspaces;
            }
        }
        protected virtual IDockingSerializationDialogService SaveLoadLayoutService { get { return null; } }

        protected virtual List<CommandViewModel> CreateAboutCommands() {
            var showAboutCommnad = new DelegateCommand(ShowAbout);
            return new List<CommandViewModel>() { new CommandViewModel("About", showAboutCommnad) { Glyph = Images.About } };
        }
        protected virtual List<CommandViewModel> CreateEditCommands() {
            var findCommand = new CommandViewModel("Find") { Glyph = Images.Find, KeyGesture = new KeyGesture(Key.F, ModifierKeys.Control) };
            var replaceCommand = new CommandViewModel("Replace") { Glyph = Images.Replace, KeyGesture = new KeyGesture(Key.H, ModifierKeys.Control) };
            var findInFilesCommand = new CommandViewModel("Find in Files") {
                Glyph = Images.FindInFiles,
                KeyGesture = new KeyGesture(Key.F, ModifierKeys.Control | ModifierKeys.Shift)
            };
            var list = new List<CommandViewModel>() { findCommand, replaceCommand, findInFilesCommand };
            CommandViewModel findReplaceDocument = new CommandViewModel("Find and Replace", list);
            findReplaceDocument.IsEnabled = true;
            findReplaceDocument.IsSubItem = true;
            return new List<CommandViewModel>() { findReplaceDocument };
        }
        protected virtual List<CommandViewModel> CreateLayoutCommands() {
            loadLayout = new CommandViewModel("Load Layout...", new DelegateCommand(OnLoadLayout)) { Glyph = Images.LoadLayout };
            saveLayout = new CommandViewModel("Save Layout...", new DelegateCommand(OnSaveLayout)) { Glyph = Images.SaveLayout };
            return new List<CommandViewModel>() { loadLayout, saveLayout };
        }
        protected T CreatePanelWorkspaceViewModel<T>() where T : PanelWorkspaceViewModel {
            return ViewModelSource<T>.Create();
        }
        protected virtual List<CommandViewModel> CreateViewCommands() {
            solutionExplorer = GetShowCommand(SolutionExplorerViewModel);
            properties = GetShowCommand(PropertiesViewModel);
            errorList = GetShowCommand(ErrorListViewModel);
            output = GetShowCommand(OutputViewModel);
            searchResults = GetShowCommand(SearchResultsViewModel);
            var themesCommands = new List<CommandViewModel>();
            foreach(Theme theme in Theme.Themes.Where(x => x.Category == Theme.VisualStudioCategory && x.Name.StartsWith("VS2019"))) {
                var command = new CommandViewModel(theme.Name.Replace("VS2019", ""), new DelegateCommand<Theme>(
                    (t) => ThemeManager.SetTheme(Application.Current.Windows.OfType<Window>().FirstOrDefault(x => x.IsActive), theme)));
                command.Glyph = (ImageSource)new SvgImageSourceExtension() { Uri = theme.SvgGlyph }.ProvideValue(null);
                themesCommands.Add(command);
            }
            CommandViewModel themesSwitcher = new CommandViewModel("Themes", themesCommands) { IsEnabled = true, IsSubItem = true };
            return new List<CommandViewModel>() { solutionExplorer, properties, errorList, output, searchResults, themesSwitcher };
        }


        protected void OpenOrCloseWorkspace(PanelWorkspaceViewModel workspace, bool activateOnOpen = true) {
            if (Workspaces.Contains(workspace))
            {
                workspace.IsClosed = !workspace.IsClosed;
            }
            else
            {
                Workspaces.Add(workspace);
                workspace.IsClosed = false;
            }
            if (activateOnOpen && workspace.IsOpened)
                SetActiveWorkspace(workspace);
        }

        bool ActivateDocument(string path) {
            var document = GetDocument(path);
            bool isFound = document != null;
            if(isFound) document.IsActive = true;
            return isFound;
        }
        List<BarModel> CreateBars() {
            return new List<BarModel>() {
                new BarModel("Main") { IsMainMenu = true, Commands = CreateCommands() },
                new BarModel("Standard") { Commands = CreateToolbarCommands() }
            };
        }
        List<CommandViewModel> CreateCommands() {
            return new List<CommandViewModel> {
                new CommandViewModel("File", CreateFileCommands()),
                new CommandViewModel("Edit", CreateEditCommands()),
                new CommandViewModel("Layouts", CreateLayoutCommands()),
                new CommandViewModel("View", CreateViewCommands()),
                new CommandViewModel("Help", CreateAboutCommands())
            };
        }
        ScenarioViewModel CreateDocumentViewModel() {
            return CreatePanelWorkspaceViewModel<ScenarioViewModel>();
        }
        List<CommandViewModel> CreateFileCommands() {
            var fileExecutedCommand = new DelegateCommand<object>(OnNewFileExecuted);
            var fileOpenCommand = new DelegateCommand<object>(OnFileOpenExecuted);

            CommandViewModel newCommand = new CommandViewModel("New") { IsSubItem = true };
            newProject = new CommandViewModel("Project...", fileExecutedCommand) { Glyph = Images.NewProject, KeyGesture = new KeyGesture(Key.N, ModifierKeys.Control | ModifierKeys.Shift), IsEnabled = false };
            newFile = new CommandViewModel("New File", fileExecutedCommand) { Glyph = Images.File, KeyGesture = new KeyGesture(Key.N, ModifierKeys.Control) };
            newCommand.Commands = new List<CommandViewModel>() { newProject, newFile };

            CommandViewModel openCommand = new CommandViewModel("Open") { IsSubItem = true, };
            openProject = new CommandViewModel("Project/Solution...") {
                Glyph = Images.OpenSolution,
                IsEnabled = false,
                KeyGesture = new KeyGesture(Key.O, ModifierKeys.Control | ModifierKeys.Shift),
            };
            openFile = new CommandViewModel("Open File", fileOpenCommand) { Glyph = Images.OpenFile, KeyGesture = new KeyGesture(Key.O, ModifierKeys.Control) };
            openCommand.Commands = new List<CommandViewModel>() { openProject, openFile };

            CommandViewModel closeFile = new CommandViewModel("Close");
            CommandViewModel closeSolution = new CommandViewModel("Close Solution") { Glyph = Images.CloseSolution };
            save = new CommandViewModel("Save") { Glyph = Images.Save, KeyGesture = new KeyGesture(Key.S, ModifierKeys.Control) };
            saveAll = new CommandViewModel("Save All") { Glyph = Images.SaveAll, KeyGesture = new KeyGesture(Key.S, ModifierKeys.Control | ModifierKeys.Shift) };

            return new List<CommandViewModel>() { newCommand, openCommand, GetSeparator(), closeFile, closeSolution, GetSeparator(), save, saveAll };
        }
        List<CommandViewModel> CreateToolbarCommands() {
            CommandViewModel start = new CommandViewModel("Start") {
                Glyph = Images.Run,
                KeyGesture = new KeyGesture(Key.F5, ModifierKeys.None),
                DisplayMode = BarItemDisplayMode.ContentAndGlyph
            };
            CommandViewModel combo = new CommandViewModel("Configuration") { IsSubItem = true, IsComboBox = true };
            combo.Commands = new List<CommandViewModel>() { new CommandViewModel("Debug"), new CommandViewModel("Release") };

            CommandViewModel cut = new CommandViewModel("Cut") { Glyph = Images.Cut, KeyGesture = new KeyGesture(Key.X, ModifierKeys.Control) };
            CommandViewModel copy = new CommandViewModel("Copy") { Glyph = Images.Copy, KeyGesture = new KeyGesture(Key.C, ModifierKeys.Control) };
            CommandViewModel paste = new CommandViewModel("Paste") { Glyph = Images.Paste, KeyGesture = new KeyGesture(Key.V, ModifierKeys.Control) };

            CommandViewModel undo = new CommandViewModel("Undo") { Glyph = Images.Undo, KeyGesture = new KeyGesture(Key.Z, ModifierKeys.Control) };
            CommandViewModel redo = new CommandViewModel("Redo") { Glyph = Images.Redo, KeyGesture = new KeyGesture(Key.Y, ModifierKeys.Control) };

            return new List<CommandViewModel>() {
                newProject, newFile, openFile, save, saveAll, GetSeparator(), combo, start,
                GetSeparator(), cut, copy, paste, GetSeparator(), undo, redo, GetSeparator(),
                solutionExplorer, properties, errorList, output, searchResults,
                GetSeparator(), loadLayout, saveLayout
            };
        }
        ScenarioViewModel GetDocument(string filePath) {
            return Workspaces.OfType<ScenarioViewModel>().FirstOrDefault(x => x.FilePath == filePath);
        }
        CommandViewModel GetSeparator() {
            return new CommandViewModel() { IsSeparator = true };
        }
        CommandViewModel GetShowCommand(PanelWorkspaceViewModel viewModel) {
            return new CommandViewModel(viewModel, new DelegateCommand(() => OpenOrCloseWorkspace(viewModel)));
        }
        void InitDefaultLayout() {
            var panels = new List<PanelWorkspaceViewModel> { SolutionExplorerViewModel, PropertiesViewModel, ErrorListViewModel };
            foreach(var panel in panels) {
                OpenOrCloseWorkspace(panel, false);
            }
        }
        void OnFileOpenExecuted(object param) {
            var document = CreateDocumentViewModel();
            if(!document.OpenFile() || ActivateDocument(document.FilePath)) {
                document.Dispose();
                return;
            }
            OpenOrCloseWorkspace(document);
        }
        void OnLoadLayout() {
            SaveLoadLayoutService.LoadLayout();
        }
        void OnNewFileExecuted(object param) {
            //string newItemName = solutionExplorerViewModel.Orgnizations.AddNewItemToRoot();
            //OpenItem(newItemName);
        }
        void OnSaveLayout() {
            SaveLoadLayoutService.SaveLayout();
        }
        void OnWorkspaceRequestClose(object sender, EventArgs e) {
            var workspace = sender as PanelWorkspaceViewModel;
            if(workspace != null) {
                workspace.IsClosed = true;
                if(workspace is ScenarioViewModel) {
                    workspace.Dispose();
                    Workspaces.Remove(workspace);
                }
            }
        }
        void OnWorkspacesChanged(object sender, NotifyCollectionChangedEventArgs e) {
            if(e.NewItems != null && e.NewItems.Count != 0)
                foreach(WorkspaceViewModel workspace in e.NewItems)
                    workspace.RequestClose += OnWorkspaceRequestClose;
            if(e.OldItems != null && e.OldItems.Count != 0)
                foreach(WorkspaceViewModel workspace in e.OldItems)
                    workspace.RequestClose -= OnWorkspaceRequestClose;
        }
        void OpenItem(string filePath) {
            if(ActivateDocument(filePath)) return;
            lastOpenedItem = CreateDocumentViewModel();
            lastOpenedItem.OpenItemByPath(filePath);
            OpenOrCloseWorkspace(lastOpenedItem);
        }
        void SetActiveWorkspace(WorkspaceViewModel workspace) {
            workspace.IsActive = true;
        }
        void ShowAbout() {
            About.ShowAbout(ProductKind.DXperienceWPF);
        }
 
    }


    public class SearchResultsViewModel : PanelWorkspaceViewModel {
        public SearchResultsViewModel() {
            DisplayName = "Search Results";
            Glyph = Images.FindInFilesWindow;
            Text = @"Matching lines: 0    Matching files: 0    Total files searched: 61";
        }

        public string Text { get; private set; }
        protected override string WorkspaceName { get { return "BottomHost"; } }
    }


    #region Bars
    public class BarModel : ViewModel {
        public BarModel(string displayName) {
            DisplayName = displayName;
        }
        public List<CommandViewModel> Commands { get; set; }
        public bool IsMainMenu { get; set; }
    }
    #endregion

 
}
